#include "ShapeContainer.h"
#include "ShapeGenerator.h"
//d'tor
ShapeContainer::~ShapeContainer()
{
	for(list<Shape*>::iterator itr = m_shape_cont.begin(); itr != m_shape_cont.end(); )
	{
		delete *itr;
		list<Shape*>::iterator tmp = itr;
		++itr;
		m_shape_cont.erase(tmp);
	}
}

void ShapeContainer::drawList(bool withHiding)
{
	if( m_shape_cont.empty() )
	{
		cout << "Shape Container is empty - Press any key to continue" << endl;
		return;
	}
	if(withHiding)
	{
		for(list<Shape*>::iterator itr = m_shape_cont.begin(); itr != m_shape_cont.end(); ++itr)
			(*itr)->drawWithHiding();
	}
	else
	{
		for(list<Shape*>::iterator itr = m_shape_cont.begin(); itr != m_shape_cont.end(); ++itr)
			(*itr)->draw();
	}
}

list<Shape*>::iterator ShapeContainer::findContainingShape(int x, int y)
{
	list<Shape*>::iterator itr = m_shape_cont.begin();
	for( ; itr != m_shape_cont.end(); ++itr)
	{
		if( (*itr)->isInShape(x,y))
			return itr;
	}
	return itr;
}

void ShapeContainer::addShapeToList(Shape *shape)
{
	shape->setShape();
	m_shape_cont.push_back(shape);
}

void ShapeContainer::bringToFront( list<Shape*>::iterator itr)
{
	Shape *tmp = *itr;
	m_shape_cont.erase(itr);
	m_shape_cont.push_front(tmp);
}

void ShapeContainer::moveToBack(list<Shape*>::iterator itr)
{
	Shape *tmp = *itr;
	m_shape_cont.erase(itr);
	m_shape_cont.push_back(tmp);
}

void ShapeContainer::copyContainer(ShapeContainer &other)
{
	for( list<Shape*>::iterator itr = other.getBeginningOfList(); itr != other.getEndOfList(); ++itr)
		m_shape_cont.push_back( (*itr)->copyShape(*itr));
}

void ShapeContainer::calcMove(bool withTransfer, ShapeContainer &work_cont)
{
	for(list<Shape*>::iterator itr = work_cont.getBeginningOfList(); itr != work_cont.getEndOfList(); ++itr)
	{
		if(!didIMove(itr)) //if shape does not move
		{
			if( (*itr)->getShiftX() != 0)
				(*itr)->setShiftXTmp( (*itr)->getShiftXTmp() + (*itr)->getShiftX());
			if( (*itr)->getShiftY() != 0)
				(*itr)->setShiftYTmp( (*itr)->getShiftYTmp() + (*itr)->getShiftY());
			continue;
		}
		(*itr)->calcShapeMove(*this,itr,withTransfer);
	}
}

void ShapeContainer::deleteShape(list<Shape*>::iterator itr)
{
	delete *itr;
	m_shape_cont.erase(itr);
}

void ShapeContainer::saveToFile(bool binary)
{
	string file_name;
	cout << "enter file name for saving: ";
	cin >> file_name;
	if(binary)
	{
		file_name += ".bin";
		ofstream out_file(file_name, ios::binary | ios::trunc);
		if( !out_file)
		{
			cerr << "error creating bin file...";
			return;
		}
		//saving number of shapes in the container to bin file
		int size = m_shape_cont.size();
		out_file.write( (const char*)&size, sizeof(int));
		//save each shape to bin file
		list<Shape*>::iterator itr = m_shape_cont.begin();
		for( int i=0; i < size; ++i, ++itr)
			(*itr)->save(out_file,binary);

		out_file.close();
	}
	else	//text
	{
		file_name += ".txt";
		ofstream out_file(file_name,ios::trunc);
		int size = m_shape_cont.size();
		out_file << size << endl;
		list<Shape*>::iterator itr = m_shape_cont.begin();
		for( int i=0; i < size; ++i, ++itr)
			(*itr)->save(out_file,binary);

		out_file.close();
	}
}

void ShapeContainer::loadFromFile(bool binary)
{
	string file_name;
	cout << "enter file name for loading: ";
	cin >> file_name;

	if(binary)
	{
		file_name += ".bin";
		ifstream in_file(file_name, ios::binary); //open file for reading only
		if( !in_file)
		{
			cerr << "error opening bin file...";
			return;
		}
		//getting number of shapes in list from bin file
		int size;
		in_file.read( (char*)&size, sizeof(int) );
		//add all the shapes to list
		for(int i=0; i < size; i++)
			m_shape_cont.push_back( ShapeGenerator::loadShape(in_file) );

		in_file.close();
	}
	else //text
	{
		file_name += ".txt";
		ifstream in_file(file_name);
		int size;
		in_file >> size;
		for(int i=0; i < size; i++)
			m_shape_cont.push_back( ShapeGenerator::loadShape(in_file,binary) );

		in_file.close();
	}
}